eventlistener = function(eventtable,event)
  pcall(eventtable[event.type],event)
end

feedchannels = {}

feed_mt = {
  private = {
    add = function(self,entry)
      table.insert(self,entry)
      eventlistener(self.eventtable,event)
      self.last = self.last + 1 
    end
  },
  __index = function (t,k)
    return feed_mt.private[k]
  end,
}

feed = function (channel,eventtable)
  local f = {}
  f.channel = channel
  f.eventtable = eventtable
  f.last=-1
  setmetatable(f,feed_mt)
  return f
end

client = {
host = 0,
port = 0,
connection = "not valid token",
history = {},
data = {
  statefeeds = {
    characters = {
      --normally I only use my feed, but I could be playing more than one character
      me = { 
        last = 0,
      }
    },
    chat = {
      --chat channels
      here = { },
      general = { },
      party = { },
      guild = { },
    },
    areas = {
      --geography
      here = { },
      world = { },
      universe = { },
    },
    organizations = {
       parties = {
       
       },
       guilds = {
       
       },
    },
    specialities = {
       questboards = {
          
       },
       auction = {
       
       }
    }
  }
}, --place wehre we store all our data
token = nil,
timeout = 1000,
viewhistory = function(self)
  for k,v in ipairs(self.history) do
    print(k,v)
  end
end,
connect = function(self, host,port)
  self.connection = assert(socket.tcp())
  self.host = host or "localhost"
  self.port = port or 111
  assert(self.connection:connect(self.host,self.port))
  assert(self.connection:setoption('keepalive',true))
  assert(self.connection:settimeout(self.timeout))
  self.token = self:send({cmd="connect"})
  return self.token
end,
sendlua = function(self,data)
  local s = marshall('data',data,";")
  table.insert(self.history,s)
  self.connection:send(string.format("%s\n",s))
end,
sendjson = function(self,data)
  local s = "json"..json.encode(data)
  table.insert(self.history,s)
  self.connection:send(string.format("%s\n",s))
end,
send    = function(self,data)
  self:sendlua(data)
  return self:receive()
end,
receive = function(self)
  return self.connection:receive("*l") --store my connection token
end,
cmd    = function(self,what,data)
  data.cmd    = what
  data.token  = self.token or "not valid token"
  return self:send(data)
end,
disconnect = function(self)
  local byebye = self:send({cmd="disconnect"})
  self.connection:shutdown("both")
  self.connection:close()
  return byebye
end,
--login/logoff are specialized commands, so it makes sense to wrap them in function
login = function(self,user,pass)
  local data ={}
  data.secret = encrypt(self.token..encrypt(pass))
  data.user   = user
  data.client = "client.lua.test"
  return self:cmd("login",data)
end,
play  = function(self,action,args)
  local data = args or {}
  data.action = action
  return self:cmd("play",data)
end,
--because the game is supposed to run on a browser it needs to run in an ajax 
--manner thus the client pulls data from the server
update  = function(self) 
  local data ={ self.data.statefeeds.characters.me.last}
  return self:cmd("update",data)
end,
logoff = function(self)
  local data ={}
  return self:cmd("logoff",data)
end,
}


--Main entrypoint
function main(args)
  local args = args or {name = "robert",pass="password"}  
  print(client:connect())
  print(client:login(args.name,args.pass))
  print(client:play("fight"))
  print(client:play("move"))
  print(client:update())
  return 1
end

